Unable to get TFlite model working because of wrong inputs - tensorflow

I have a model called RepNet I want to run on TFlite for Kotlin, the interpreter provides the shape and DataType of the data, but I simply could not get the data to work with the interpreter, I have problems getting it to the correct shape.
The data shape is this :
But I simply can't get my list of Images to match the correct shape, I'll include my code down below if someone could help me make the right transformations to get it working and thank you.
class TestActivity2 : AppCompatActivity() {
#RequiresApi(Build.VERSION_CODES.P)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_test2)
//val file = File("/assets/repnet.tflite")
//Log.d("Path", file.path)
var file = loadModelFile(assets,"repnet2.5.tflite")
var interpreter = Interpreter(file!!)
var counts = getCount(interpreter)
interpreter.close()
Log.d("Counts", counts.toString())
}
#RequiresApi(Build.VERSION_CODES.P)
private fun getImages(): MutableList<TensorImage> {
val mmd = MediaMetadataRetriever()
val path = "/sdcard/bicycle.mp4"
mmd.setDataSource(path)
var duration = mmd.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_FRAME_COUNT)
var inputImages = mutableListOf<TensorImage>()
Log.d("Duration",duration.toString())
if (duration != null) {
for (i in 0 until 50) {
var bitmap: Bitmap?
Log.d("Frame", i.toString())
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
bitmap = mmd.getFrameAtIndex(i)
if (bitmap != null) {
bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true)
inputImages.add(TensorImage.fromBitmap(bitmap))
}
}
} catch (e: Exception) {
println("Could not convert image to BitMap")
e.printStackTrace()
}
}
}
return inputImages
}
fun preprocessImages(images: List<TensorImage>): List<TensorImage> {
val imageMean = 127.5F
val imageStd = 127.5F
val imageSize = 224
val imageProcessor = ImageProcessor.Builder()
.add(CastOp(DataType.FLOAT32))
.add(NormalizeOp(imageMean,imageStd))
.add(ResizeOp(imageSize,imageSize,ResizeOp.ResizeMethod.BILINEAR))
.build()
val preprocessedImages = mutableListOf<TensorImage>()
for (image in images) {
val processedImage = imageProcessor.process(image)
preprocessedImages.add(processedImage)
}
return preprocessedImages
}
#RequiresApi(Build.VERSION_CODES.P)
fun getCount(interpreter: Interpreter): Int {
var images = getImages()
images = preprocessImages(images as List<TensorImage>).toMutableList()
val batchImages = mutableListOf<TensorBuffer>()
for(img in images) {
batchImages.add(img.tensorBuffer)
}
var inputBuffer = TensorBuffer.createDynamic(DataType.FLOAT32)
var outputBuffer = TensorBuffer.createFixedSize(interpreter.getOutputTensor(0).shape(),interpreter.getOutputTensor(0).dataType())
interpreter.run(images[0].tensorBuffer,outputBuffer.buffer)
Log.d("Result", outputBuffer.floatArray[0].toString())
Log.d("Output", outputBuffer.toString())
return 0
}
#Throws(IOException::class)
private fun loadModelFile(assets: AssetManager, modelFilename: String): MappedByteBuffer? {
val fileDescriptor = assets.openFd(modelFilename)
val inputStream = FileInputStream(fileDescriptor.fileDescriptor)
val fileChannel: FileChannel = inputStream.getChannel()
val startOffset = fileDescriptor.startOffset
val declaredLength = fileDescriptor.declaredLength
return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength)
}
}

Related

My response data return " kotlinx.coroutines.flow.SafeFlow#1493a74"

I am trying to do dictionary app using kotlin language. I built the project with mvvm and clean architecture. I have been trying to pull vocabulary information from the internet using jsoap. I am using flow for data. I couldnt find where the issiue is. Normally, the words should appear on the screen or I should be able to see the data when I println on the console.But I can't see it on the screen or on the console, probably because the data coming from the internet is as follows.
kotlinx.coroutines.flow.SafeFlow#1493a74
I am sharing my codes below
ExtractedData
data class ExtractedData(
var id :Int = 0,
var word:String = "",
var meaning :String = ""
)
I created ExtractedData class to represent vocabulary or word data from internet
WordInfoRepositoryImpl
class WordInfoRepositoryImpl #Inject constructor(
private val api:DictionaryApi
) : WordInfoRepository {
//get words with meanings on the internet using jsoap
override fun getEventsList(): Flow<Resource<MutableList<ExtractedData>>> = flow {
emit(Resource.Loading())
val listData = mutableListOf<ExtractedData>()
try {
val url = "https://ielts.com.au/australia/prepare/article-100-new-english-words-and-phrases-updated-2020"
val doc = withContext(Dispatchers.IO){
Jsoup.connect(url).get()//-->Here it gives the following warning even though I have it in withContext `Inappropriate blocking method call`
}
val table = doc.select("table")
val rows = table.select("tr")
val eventsSize = rows.size
for (i in 1 until eventsSize) {
val row = rows[i]
val cols = row.select("td")
val word = cols[0].text()
val meaning = cols[1].text()
listData.add(ExtractedData(i,word,meaning))
}
}
catch (e: IOException) {
emit(Resource.Error("IO Exception"))
}
catch (e : HttpException) {
emit(Resource.Error("HTTP EXCEPTION"))
}
emit(Resource.Success(listData))
}
}
getEventsList is in my WordInfoRepositoryImpl class in my data layer here I am pulling data from internet using jsoap
WordInfoRepository
interface WordInfoRepository {
fun getEventsList(): Flow<Resource<MutableList<ExtractedData>>>
}
this is the interface that I reference wordInforepositoryImpl in the data layer in my interface domain layer
GetWordsAndMeaningsOnTheInternetUseCase
class GetWordsAndMeaningsOnTheInternetUseCase#Inject constructor(
private val repository: WordInfoRepository
){
operator fun invoke() : Flow<Resource<MutableList<ExtractedData>>> {
return repository.getEventsList()
}
}
GetWordsAndMeaningsOnTheInternetUseCase is my usecase in my domain layer
ViewModel
#HiltViewModel
class MostUsedWordScreenViewModel #Inject constructor(
private val getWordsAndMeaningsOnTheInternetUseCase: GetWordsAndMeaningsOnTheInternetUseCase
) : ViewModel() {
private var searchJob: Job? = null
private val _state = mutableStateOf(MostUsedWordState())
val state: State<MostUsedWordState> = _state
init {
fetchData()
}
private fun fetchData() {
searchJob?.cancel()
searchJob = viewModelScope.launch(IO) {
getWordsAndMeaningsOnTheInternetUseCase().onEach { result ->
when (result) {
is Resource.Success -> {
_state.value = state.value.copy(
mostWordUsedItems = result.data ?: mutableListOf(),
isLoading = false
)
}
is Resource.Error -> {
_state.value = state.value.copy(
mostWordUsedItems = result.data ?: mutableListOf(),
isLoading = false
)
}
is Resource.Loading -> {
_state.value = state.value.copy(
mostWordUsedItems = result.data ?: mutableListOf(),
isLoading = true
)
}
}
}
}
}
}
MostUsedWordScreen
#Composable
fun MostUsedWordScreen(viewModel: MostUsedWordScreenViewModel = hiltViewModel()) {
val state = viewModel.state.value
println("state --- >>> "+state.mostWordUsedItems)
LazyColumn(
modifier = Modifier.fillMaxSize()
) {
items(state.mostWordUsedItems.size) { i ->
val wordInfo = state.mostWordUsedItems[i]
if(i > 0) {
Spacer(modifier = Modifier.height(8.dp))
}
MostUsedWordItem(word = wordInfo)
if(i < state.mostWordUsedItems.size - 1) {
Divider()
}
}
}
}
#Composable
fun MostUsedWordItem(word : ExtractedData ) {
// println("this is MostUsedWordItem")
Column(modifier = Modifier
.padding(5.dp)
.fillMaxWidth()) {
Text(text = word.word,
modifier = Modifier.padding(3.dp),
textAlign = TextAlign.Center,
fontSize = 18.sp,
)
}
}
It is included in the MostUsedWordScreenViewModel and MostUsedWordScreen presententation layer
Where I println("state --- >>> "+state.mostWordUsedItems) in MostUsedWordScreen, the state console shows as empty like this System.out: state --- >>> []
I tried to explain as detailed as I can, I hope you can understand.
A Flow doesn't do anything until you call a terminal operator on it. You called onEach, which is not a terminal operator. You should use collect. Or you can avoid the nesting inside a launch block by using onEach and launchIn, which does the same thing as launching a coroutine and calling collect() on the flow. You don't need to specify Dispatchers.IO here because nothing in your Flow is blocking. You correctly wrapped the blocking call in withContext(Dispatchers.IO), and the warning is a false positive. That's a well-known bug in their compiler inspection.
searchJob = getWordsAndMeaningsOnTheInternetUseCase().onEach { result ->
when (result) {
is Resource.Success -> {
_state.value = state.value.copy(
mostWordUsedItems = result.data ?: mutableListOf(),
isLoading = false
)
}
is Resource.Error -> {
_state.value = state.value.copy(
mostWordUsedItems = result.data ?: mutableListOf(),
isLoading = false
)
}
is Resource.Loading -> {
_state.value = state.value.copy(
mostWordUsedItems = result.data ?: mutableListOf(),
isLoading = true
)
}
}
}.launchIn(viewModelScope)
By the way, you need to move your emit(Success...) inside your try block. The way it is now, when there is an error, the error will immediately get replaced by a Success with empty list.
Side note, I recommend avoiding passing MutableLists around between classes. You have no need for them and it's a code smell. Sharing mutable state between classes is error-prone. I don't think there is any justification for using a Flow<MutableList> instead of a Flow<List>.
You rarely even need a MutableList locally in a function. For example, you could have done in your try block:
val listData = List(eventsSize - 1) {
val row = rows[it + 1]
val cols = row.select("td")
val word = cols[0].text()
val meaning = cols[1].text()
ExtractedData(i,word,meaning)
}
emit(Resource.Success(listData))

Loading state adapter is always loading

My task is to load recyclerView and show pagination which I both implemented.
I also implemented LoadingState for adapter.
ApiCall:
#GET("top-headlines?sources=bbc-news,techcrunch&apiKey=${BuildConfig.API_KEY}")
suspend fun getTopHeadlinesArticles(
#Query("page") page:Int = 1,
#Query("q") query: String,
) : Response<ArticleListResponse>
I wont show paging because it is working so I will jump to repository:
fun getSearchResult(query: String) =
Pager(
config = PagingConfig(
pageSize = 1,
maxSize = 20,
enablePlaceholders = false
),
pagingSourceFactory = { ArticlePaging(newsService, query)}
).flow
ViewModel:
#OptIn(ExperimentalCoroutinesApi::class)
val news = _currentQuery.flatMapLatest { query ->
articleRepository.getSearchResult(query).cachedIn(viewModelScope)
}
Fragment:
binding.recyclerViewTop.layoutManager = LinearLayoutManager(context)
binding.recyclerViewTop.adapter = adapter.withLoadStateHeaderAndFooter(
header = ArticleLoadStateAdapter { adapter.retry() },
footer = ArticleLoadStateAdapter { adapter.retry() }
)
lifecycleScope.launchWhenCreated {
viewModel.news.collect { articles ->
adapter.submitData(articles)
}
}
And LoadStateViewHolder in LoadStateAdapter:
init {
binding.buttonRetry.setOnClickListener {
retry.invoke()
}
}
fun bind(loadState: LoadState) {
binding.apply {
progressBar.isVisible = loadState is LoadState.Loading
buttonRetry.isVisible = loadState !is LoadState.Loading
textViewError.isVisible = loadState !is LoadState.Loading
}
}
I already predefined DEFAULT_QUERY so I only get 1 Article.
Problem is that progressBar loading is always visible and I have no more articles to show.
Edit: when i have at least 10 items to show this works fine
Edit 2nd: Add ArticlePagingSource if that can help
override fun getRefreshKey(state: PagingState<Int, ArticleResponse>): Int? {
return state.anchorPosition?.let {
val anchorPage = state.closestPageToPosition(it)
anchorPage?.prevKey?.plus(1) ?: anchorPage?.nextKey?.minus(1)
}
}
try {
val currentPageList = params.key ?: 1
response = if(query != ""){
newsService.getTopHeadlinesArticles(currentPageList, query)
} else{
newsService.getTopHeadlinesArticles(currentPageList)
}
val responseList = mutableListOf<ArticleResponse>()
val data = response.body()?.articleResponses ?: emptyList()
responseList.addAll(data)
val prevKey = if (currentPageList == 1) null else currentPageList - 1
return LoadResult.Page(
responseList,
prevKey,
currentPageList.plus(1)
)

Scanning with ML Firebase Barcode doesn't recognize format

I have been trying to use the MLKit to scan a barcode however I don't seem to get anything on return, the info that I'm getting back is
W/libc: Access denied finding property "ro.hardware.chipname"
This is the code that I'm trying, it does enter in the success listener however I doesn't seem to recognize the format.
private fun scanBarcodes(bitmap: Bitmap) {
val options = BarcodeScannerOptions.Builder()
.setBarcodeFormats(
Barcode.FORMAT_CODABAR,
Barcode.FORMAT_UPC_A,
Barcode.FORMAT_UPC_E
)
.build()
val scanner = BarcodeScanning.getClient(options)
val image = InputImage.fromBitmap(bitmap, 0)
scanner.process(image)
.addOnSuccessListener { barcodes ->
// It is succesful
for (barcode in barcodes) {
val bounds = barcode.boundingBox
val corners = barcode.cornerPoints
val rawValue = barcode.rawValue
Log.d("RAWVALUE ->>>", rawValue.toString())
when (barcode.valueType) {
Barcode.FORMAT_UPC_A -> {
Log.d("TASK SUCCESFUL ->>>>>>", "UPC A")
val upc = barcode.url
}
Barcode.FORMAT_UPC_E -> {
Log.d("TASK SUCCESFUL ->>>>>>", "UPC E")
}
Barcode.FORMAT_CODABAR -> {
val title = barcode.url!!.title
val url = barcode.url!!.url
}
}
}
}
.addOnFailureListener {
Log.d(TAG, "Problem")
}
}
The BitMap that I'm passing the scanBarcodes function is the one obtained underneath
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 100 && resultCode == RESULT_OK) {
imageUri = data?.data!!
if (binding.switchCamera?.isChecked == true)
Picasso.get()!!.load(imageUri).resize(300, 300).centerCrop()
.into(binding.imageButton)
}
if (requestCode == cameraCode && resultCode == RESULT_OK) {
imageBitmap = data?.extras?.get("data") as Bitmap
val baos = ByteArrayOutputStream()
imageBitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos)
data2 = baos.toByteArray()
val file = File(cacheDir, "filename.jpg")
file.createNewFile()
val fileOS = FileOutputStream(file)
fileOS.write(data2)
fileOS.flush()
fileOS.close()
if (binding.switchCamera?.isChecked == true) {
binding.imageButton.setImageBitmap(imageBitmap)
} else {
scanBarcodes(imageBitmap)
}
}
}

Incompatible types: Int and Article

I am developing news app I have implemented multipleview types in recyclerview adapter class but I am getting following error
Incompatible types: Int and Article
below BBCSportAdapter class where I have implemented multipleview types
#Suppress("UNREACHABLE_CODE")
class BBCSportAdapter(private val listViewType: List<Int>) : RecyclerView.Adapter<BBCSportAdapter.MyViewHolder>() {
companion object {
val ITEM_A = 1
var ITEM_B = 2
}
var articleList: List<Article> = listOf()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val inflater =
LayoutInflater.from(parent.context)
return when (viewType) {
ITEM_A -> ViewHolderItemA(inflater.inflate(R.layout.bbc_sport_list, null))
else -> {
ViewHolderItemB(inflater.inflate(R.layout.bbc_sport_item, null))
}
}
}
#SuppressLint("NewApi")
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val viewType = articleList[position]
when (viewType) {
ITEM_A -> {
val viewHolderA = holder as ViewHolderItemA
Picasso.get().load(articleList[position].urlToImage)
.into(viewHolderA.topFlameImageView)
}else -> {
val viewHolderB = holder as ViewHolderItemB
}
}
}
override fun getItemCount(): Int {
return articleList.size
}
// holder.articleTitle.text = articleList[position].title
// holder . articleSourceName . text = articleList [position].source.name
// Picasso . get ().load(articleList.get(position).urlToImage).into(holder.image)
//
// val input = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX")
// val output = SimpleDateFormat("dd/MM/yyyy")
// var d = Date()
// try {
// d = input.parse(articleList[5].publishedAt)
// } catch (e: ParseException) {
// try {
// val fallback = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
// fallback.timeZone = TimeZone.getTimeZone("UTC")
// d = fallback.parse(articleList[5].publishedAt)
// } catch (e2: ParseException) {
// // TODO handle error
// val formatted = output.format(d)
// val timelinePoint = LocalDateTime.parse(formatted)
// val now = LocalDateTime.now()
//
// var elapsedTime = Duration.between(timelinePoint, now)
//
// println(timelinePoint)
// println(now)
// elapsedTime.toMinutes()
//
// holder.articleTime.text = "${elapsedTime.toMinutes()}"
// }
// }
// }
fun setMovieListItems(articleList: List<Article>) {
this.articleList = articleList
notifyDataSetChanged()
}
open inner class MyViewHolder(itemView: View?) : RecyclerView.ViewHolder(itemView!!){}
inner class ViewHolderItemA(itemView: View) : MyViewHolder(itemView) {
val topFlameImageView: ImageView = itemView.findViewById(R.id.topFlameImageView)
}
inner class ViewHolderItemB(itemView: View?) : MyViewHolder(itemView) {
val image: ImageView = itemView!!.findViewById(R.id.imageView)
val articleTitle: TextView = itemView!!.findViewById(R.id.articleTitle)
val articleSourceName: TextView = itemView!!.findViewById(R.id.articleSourceName)
val imageCategory: ImageView = itemView!!.findViewById(R.id.imageCategory)
val articleTime: TextView = itemView!!.findViewById(R.id.articleTime)
}
}
I have followed this link https://github.com/CoderJava/Multiple-View-Type-RecyclerView-Kotlin-Android/blob/master/app/src/main/java/com/ysn/multipleviewtypeexample/AdapterRecyclerView.kt
In your onBindViewHolder articleList is list of artical but in your when statement you are comparing Article with an Int i.e. ITEM_A, which is wrong. Instead you should have some type in your article object and comparison is based on that type. Moreover you have not implemented getItemViewType() where you can make decision which view will be inflated. In your case viewType in parameter of oncreateViewHolder will always return 0 and else condition will be executed always and you will always have single type of view.

Cannot infer a type for this parameter please specify it explicitly?

I have recently developed android app using Kotlin but I am getting the following error
Cannot infer a type for this parameter. Please specify it explicitly
below screenshot of the error
below my class where I am getting error
class AddBookingActivity : AppCompatActivity() {
#BindView(R.id.attendees_recycler_view)
internal var mAttendeeRecyclerView: RecyclerView? = null
#BindView(R.id.start_time_edit_text)
internal var mStartTime: EditText? = null
#BindView(R.id.end_time_edit_text)
internal var mEndTime: EditText? = null
private var mAttendeeName: EditText? = null
private var mAttendeeEmail: EditText? = null
private var mAttendeePhoneNumber: EditText? = null
private var mAttendeeAdapter: AttendeeAdapter? = null
private var mAlertDialog: AlertDialog? = null
private val mAttendeeItemList = ArrayList<AttendeeItem>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_add_booking)
ButterKnife.bind(this)
mAttendeeRecyclerView!!.layoutManager = LinearLayoutManager(this)
mAttendeeAdapter = AttendeeAdapter(this)
mAttendeeAdapter!!.setAttendeeList(mAttendeeItemList)
mAttendeeRecyclerView!!.adapter = mAttendeeAdapter
}
#OnClick(R.id.toolbar_back_button)
internal fun onBackButtonClicked() {
onBackPressed()
}
#OnClick(R.id.start_time_edit_text)
internal fun onStartTimeClicked() {
showTimePickerDialog(mStartTime)
}
#OnClick(R.id.end_time_edit_text)
internal fun onEndTimeClicked() {
showTimePickerDialog(mEndTime)
}
#OnClick(R.id.fab_add_attendee)
internal fun onAddAttendeeClicked() {
val inflater = this.layoutInflater
val dialogView = inflater.inflate(R.layout.add_attendee_view, null)
mAttendeeName = dialogView.findViewById(R.id.attendee_name)
mAttendeeEmail = dialogView.findViewById(R.id.attendee_email)
mAttendeePhoneNumber = dialogView.findViewById(R.id.attendee_phone_number)
mAlertDialog = AlertDialog.Builder(this, R.style.AlertDialog)
.setTitle("Input attendee details")
.setPositiveButton("Add") { dialog, which ->
val item = AttendeeItem()
item.name = mAttendeeName!!.text.toString()
item.email = mAttendeeEmail!!.text.toString()
item.phoneNumber = mAttendeePhoneNumber!!.text.toString()
mAttendeeItemList.add(item)
mAttendeeAdapter!!.setAttendeeList(mAttendeeItemList)
mAttendeeAdapter!!.notifyItemInserted(mAttendeeItemList.size)
}
.setNegativeButton("Cancel", null)
.setView(dialogView).create()
mAlertDialog!!.show()
}
private fun showTimePickerDialog(editText: EditText?) {
val myCalender = Calendar.getInstance()
val hour = myCalender.get(Calendar.HOUR_OF_DAY)
val minute = myCalender.get(Calendar.MINUTE)
#SuppressLint("DefaultLocale")
val myTimeListener = { view, hourOfDay, minute1 ->
if (view.isShown()) {
myCalender.set(Calendar.HOUR_OF_DAY, hourOfDay)
myCalender.set(Calendar.MINUTE, minute1)
editText!!.setText(String.format(String.format("%s:%s", hourOfDay.toString(), minute1.toString())))
}
}
val timePickerDialog = TimePickerDialog(this, android.R.style.Theme_Holo_Light_Dialog_NoActionBar, myTimeListener, hour, minute, true)
timePickerDialog.setTitle("Choose hour:")
timePickerDialog.window!!.setBackgroundDrawableResource(android.R.color.transparent)
timePickerDialog.show()
}
}
You have to specify the interface to help Kotlin compiler:
#SuppressLint("DefaultLocale")
val myTimeListener = TimePickerDialog.OnTimeSetListener { view, hourOfDay, minute1 ->
if (view.isShown()) {
myCalender.set(Calendar.HOUR_OF_DAY, hourOfDay)
myCalender.set(Calendar.MINUTE, minute1)
editText!!.setText(String.format(String.format("%s:%s", hourOfDay.toString(), minute1.toString())))
}
}